package com.yy.wga.mp.module.goods.manager;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.yy.wga.mp.module.goods.request.GoodsTransferReq;
import com.yy.wga.mp.module.goods.response.GoodSpuListResp;
import com.yy.wga.mp.module.goods.response.GoodsInfoResp;
import com.yy.wga.mp.module.goods.response.GoodsProductPromotionLinkResp;
import com.yy.wga.mp.module.goods.response.GoodsShareResp;
import com.yy.wga.mp.module.goods.api.response.product.GetHeadSupplierProductDetailDTO;
import com.yy.wga.mp.module.goods.api.response.product.ProductPromotionInfoLinkDTO;
import com.yy.wga.mp.module.goods.api.response.product.ProductPromotionQrcodeInfoDTO;
import com.yy.wga.mp.module.goods.api.response.product.PromoteProductDetailDTO;
import com.yy.wga.mp.module.goods.api.response.product.PromoteProductListDTO;
import com.yy.wga.mp.module.goods.api.response.product.PromoterSingleProductPromotionInfoDTO;
import com.yy.wga.mp.module.goods.entity.bo.CategoryBO;
import com.yy.wga.mp.module.goods.entity.bo.GetPromoteGoodsTaskV2BO;
import com.yy.wga.mp.module.goods.entity.bo.GoodsIdBO;
import com.yy.wga.mp.module.goods.request.GetCategoryGoodsReq;
import com.yy.wga.mp.module.goods.request.GetSpuListReq;
import com.yy.wga.mp.common.dto.UserCacheDTO;
import com.yy.wga.common.core.exception.BusinessException;
import com.yy.wga.mp.common.interceptor.RequestUserHolder;
import com.yy.wga.mp.common.utils.common.EnvUtils;
import com.yy.wga.mp.common.utils.common.JsonUtils;
import com.yy.wga.mp.common.utils.common.SpringUtils;
import com.yy.wga.mp.common.utils.common.StringUtils;
import com.yy.wga.mp.common.utils.mapping.BeansUtils;
import com.yy.wga.mp.module.goods.api.request.product.GetHeadSupplierProductDetailReq;
import com.yy.wga.mp.module.goods.api.request.product.GetProductPromotionInfoReq;
import com.yy.wga.mp.module.goods.api.request.product.GetPromoteProductDetailReq;
import com.yy.wga.mp.module.goods.api.request.product.GetPromoteProductListReq;
import com.yy.wga.module.goods.api.response.product.*;
import com.yy.wga.mp.module.goods.common.constant.RedisConstants;
import com.yy.wga.mp.module.goods.common.enums.ECategory;
import com.yy.wga.module.goods.entity.bo.*;
import com.yy.wga.module.goods.request.*;
import com.yy.wga.module.goods.response.*;
import com.yy.wga.mp.module.promoter.manager.PromoterManager;
import com.yy.wga.mp.module.promoter.response.PromoterStatusResp;
import com.yy.wga.mp.module.promoter.service.IProductService;
import com.yy.wga.mp.module.resource.entity.pojo.ResourceGoodsCategoryDO;
import com.yy.wga.mp.module.resource.entity.pojo.ResourceGoodsCategoryExtendDO;
import com.yy.wga.mp.module.resource.service.ResourceGoodsCategoryExtendService;
import com.yy.wga.mp.module.resource.service.ResourceGoodsCategoryService;
import com.yy.wga.mp.module.user.enums.EUserGrade;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * description
 *
 * @author <a href="mailto:guochao@dingtalk.com"> guochao </a>
 * @version 1.0.0   2021/4/1,14:54
 * @since 1.0.0     2021/4/1,14:54
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ProductManager {

    private final IProductService productService;

    @Resource(name = "getGoodsInfoExecutor")
    private ThreadPoolTaskExecutor getGoodsInfoExecutor;

    @Resource
    private ResourceGoodsCategoryService resourceGoodsCategoryService;
    @Resource
    private ResourceGoodsCategoryExtendService goodsCategoryExtendService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static List<String> API_ERROR_CODE_TO_DELETE_GOODS = Arrays.asList("10024004");

    /**
     * 获取商品列表
     *
     * @param request
     * @return
     */
    public GoodSpuListResp getSpuList(GetSpuListReq request) {
        GoodSpuListResp resp = new GoodSpuListResp();

        GetPromoteProductListReq getPromoteProductListReq = new GetPromoteProductListReq();
        BeansUtils.copyProperties(request, getPromoteProductListReq);
        // 首页搜索使用公开计划
        getPromoteProductListReq.setPlanType(2);
        // 加入品类
        Integer categoryType = request.getCategoryType();
        if (Objects.nonNull(categoryType)) {
            CategoryBO category = ECategory.parseCategory(categoryType);
            if (Objects.nonNull(category)) {
                getPromoteProductListReq.setCategory(category);
            }
        }
        PromoteProductListDTO promoteProductListResp = productService.getPromoteProductList(getPromoteProductListReq);
        List<PromoteProductListDTO.Product> productList = promoteProductListResp.getProductList();
        // 搜索不到 则切割最后一个次搜索
        if (CollectionUtils.isEmpty(productList) && StringUtils.isNotBlank(request.getKeyword())) {
            // 关键词减少最后面减少一个字查询
            String keyword = request.getKeyword();
            boolean flag = true;
            int count = 0;
            do {
                keyword = keyword.substring(0, keyword.length() - 1);
                getPromoteProductListReq.setKeyword(keyword);
                promoteProductListResp = productService.getPromoteProductList(getPromoteProductListReq);
                productList = promoteProductListResp.getProductList();
                count++;
                if (!CollectionUtils.isEmpty(productList) || keyword.length() <= 1 || count > 2) {
                    flag = false;
                }
            } while (flag);
        }

        UserCacheDTO userCache = RequestUserHolder.getUserCache();
        EUserGrade userGrade = EUserGrade.getByType(userCache.getGrade(), userCache.getLevel());


        List<GoodsIdBO> goodsIdBOList = productList.stream().map(product -> {
            return GoodsIdBO.builder().productId(product.getProductId()).shopAppid(product.getShopAppid()).build();
        }).collect(Collectors.toList());


        GetPromoteGoodsTaskV2BO getPromoteGoodsTaskBO = GetPromoteGoodsTaskV2BO.builder()
                .goodsIdBOList(goodsIdBOList)
                .userGrade(userGrade)
                .appKey(RequestUserHolder.getAppKey())
                .playType(getPromoteProductListReq.getPlanType())
                .useDb(false)
                .build();

        List<GoodsInfoResp> respList = getPromoteGoodsTaskBO.execute();

        resp.setList(respList);
        resp.setNextKey(promoteProductListResp.getNextKey());
        return resp;
    }


    public GoodsShareResp share(@Valid GoodsTransferReq request) {
        GoodsShareResp resp = new GoodsShareResp();
        UserCacheDTO userCache = RequestUserHolder.getUserCache();
        EUserGrade userGrade = EUserGrade.getByType(userCache.getGrade(), userCache.getLevel());
        String openId = null;
        if (Objects.isNull(userGrade) || Objects.equals(userGrade, EUserGrade.COMMON)) {
            openId = EnvUtils.get("goods.share.default.openId");
        } else {
            openId = userCache.getOpenId();
        }

        // 先校验是否注册绑定通过
        PromoterStatusResp promoterStatus = SpringUtils.getBean(PromoterManager.class).getPromoterStatus(openId);
        if (!Objects.equals(promoterStatus.getType(), 0)) {
            resp.setNeedRegisterAndBind(true);
            return resp;
        }

        GetProductPromotionInfoReq getProductPromotionInfoReq = new GetProductPromotionInfoReq();


        getProductPromotionInfoReq.setSharerOpenid(openId);
        String productShortLink = request.getShortLink();
        if (StringUtils.isNotBlank(productShortLink)) {
            getProductPromotionInfoReq.setProductShortLink(productShortLink);
        } else if (StringUtils.isNotBlank(request.getSpuId())) {
            getProductPromotionInfoReq.setProductId(Long.valueOf(request.getSpuId()));
            getProductPromotionInfoReq.setShopAppid(request.getShopAppid());
        }
        ProductPromotionInfoLinkDTO productPromotionLinkInfo = productService.getProductPromotionLinkInfo(getProductPromotionInfoReq);
        ProductPromotionQrcodeInfoDTO productPromotionQrcodeInfo = productService.getProductPromotionQrcodeInfo(getProductPromotionInfoReq);
        resp.setShortLink(productPromotionLinkInfo.getShortLink());
        resp.setQrcodeUrl(productPromotionQrcodeInfo.getQrcodeUrl());
        return resp;
    }

    public GoodsProductPromotionLinkResp getProductPromotionLink(@Valid GoodsTransferReq request) {
        GoodsProductPromotionLinkResp resp = new GoodsProductPromotionLinkResp();
        UserCacheDTO userCache = RequestUserHolder.getUserCache();
        EUserGrade userGrade = EUserGrade.getByType(userCache.getGrade(), userCache.getLevel());
        String openId = null;
        if (Objects.isNull(userGrade) || Objects.equals(userGrade, EUserGrade.COMMON)) {
            openId = EnvUtils.get("goods.share.default.openId");
        } else {
            openId = userCache.getOpenId();
        }

        // 先校验是否注册绑定通过
        PromoterStatusResp promoterStatus = SpringUtils.getBean(PromoterManager.class).getPromoterStatus(openId);
        if (!Objects.equals(promoterStatus.getType(), 0)) {
            resp.setNeedRegisterAndBind(true);
            return resp;
        }

        GetProductPromotionInfoReq getProductPromotionInfoReq = new GetProductPromotionInfoReq();


        getProductPromotionInfoReq.setSharerOpenid(openId);
        String productShortLink = request.getShortLink();
        if (StringUtils.isNotBlank(productShortLink)) {
            getProductPromotionInfoReq.setProductShortLink(productShortLink);
        } else if (StringUtils.isNotBlank(request.getSpuId())) {
            getProductPromotionInfoReq.setProductId(Long.valueOf(request.getSpuId()));
            getProductPromotionInfoReq.setShopAppid(request.getShopAppid());
        }
        PromoterSingleProductPromotionInfoDTO promoterSingleProductPromotionInfo = productService.getPromoterSingleProductPromotionInfo(getProductPromotionInfoReq);
        resp.setProductPromotionLink(promoterSingleProductPromotionInfo.getProductPromotionLink());
        return resp;
    }

    public PageBean<GoodsInfoResp> getCategoryGoods(@Valid GetCategoryGoodsReq request) {
        String appKey = RequestUserHolder.getAppKey();

        Integer categoryId = request.getCategoryId();
        ResourceGoodsCategoryDO resourceGoodsCategoryDO = resourceGoodsCategoryService.getById(categoryId);
        if (Objects.isNull(resourceGoodsCategoryDO)) {
            throw new BusinessException("分类不存在");
        }
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<ResourceGoodsCategoryExtendDO> extendList = goodsCategoryExtendService.list(new LambdaQueryWrapper<ResourceGoodsCategoryExtendDO>()
                .eq(ResourceGoodsCategoryExtendDO::getAppKey, appKey)
                .eq(ResourceGoodsCategoryExtendDO::getCategoryId, categoryId)
                .orderByDesc(ResourceGoodsCategoryExtendDO::getSort));


        // 获取商品信息
        List<GoodsIdBO> goodsIdBOList = extendList.stream().map(record -> {
            return GoodsIdBO.builder().shopAppid(record.getShopAppid()).productId(record.getSpuId()).build();
        }).collect(Collectors.toList());

        GetPromoteGoodsTaskV2BO getPromoteGoodsTaskV2BO = GetPromoteGoodsTaskV2BO.builder()
                .goodsIdBOList(goodsIdBOList)
                .userGrade(RequestUserHolder.getUserGrade())
                .appKey(appKey)
                .playType(1)
                .useDb(true)
                .build();

        List<GoodsInfoResp> respList = getPromoteGoodsTaskV2BO.execute();

        Map<String, ResourceGoodsCategoryExtendDO> extendDOMap = extendList.stream().collect(Collectors.toMap(item -> {
            return String.valueOf(item.getShopAppid() + "_" + item.getSpuId());
        }, Function.identity()));

        Integer supportSubsidyAmount = resourceGoodsCategoryDO.getSupportSubsidyAmount();
        boolean supportSubsidyAmountFlag = Objects.equals(supportSubsidyAmount, 1);

        for (GoodsInfoResp resp : respList) {
            String key = resp.getShopAppid() + "_" + resp.getSpuId();
            if (extendDOMap.containsKey(key)) {
                ResourceGoodsCategoryExtendDO extendDO = extendDOMap.get(key);
                resp.setRecommendReason(extendDO.getRecommendReason());
                Integer commissionValue = resp.getCommissionValue();
                Integer subsidyAmount = extendDO.getSubsidyAmount();

                if (supportSubsidyAmountFlag) {
                    if (commissionValue - subsidyAmount >= 0) {
                        commissionValue = commissionValue - subsidyAmount;
                    } else {
                        subsidyAmount = commissionValue;
                        commissionValue = 0;
                    }
                    resp.setSubsidyAmount(subsidyAmount);
                    resp.setCommissionValue(commissionValue);
                } else {
                    resp.setSubsidyAmount(0);
                    resp.setCommissionValue(commissionValue);
                }
            } else {
                resp.setRecommendReason(StringUtils.EMPTY);
                resp.setSubsidyAmount(0);
            }
        }

        PageBean<GoodsInfoResp> pageBean = new PageBean<>();
        pageBean.setPageInfo(extendList);
        pageBean.setList(respList);
        return pageBean;
    }

    /**
     * 获取推客商品
     *
     * @param goodsIdBO goodsIdBO
     * @return GetHeadSupplierProductDetailDTO.Product
     */
    public PromoteProductDetailDTO.Product getPromoteProductDetail(Integer planType,GoodsIdBO goodsIdBO) {
        String appKey = RequestUserHolder.getAppKey();
        String redisKey = RedisConstants.getPromoteGoodsKey(appKey, planType, goodsIdBO.getShopAppid(), goodsIdBO.getProductId());
        String json = stringRedisTemplate.opsForValue().get(redisKey);
        boolean match = true;
        if (StringUtils.isBlank(json)) {
            match = this.syncPromoteProductDetail(planType,goodsIdBO);
        }
        return match ? JsonUtils.parseObject(json, PromoteProductDetailDTO.Product.class) : null;
    }

    /**
     * 同步推客商品
     *
     * @param goodsIdBO goodsIdBO
     * @return boolean
     */
    public boolean syncPromoteProductDetail(Integer planType,GoodsIdBO goodsIdBO) {
        String appKey = RequestUserHolder.getAppKey();
        String redisKey = RedisConstants.getPromoteGoodsKey(appKey,planType, goodsIdBO.getShopAppid(), goodsIdBO.getProductId());
        GetPromoteProductDetailReq getPromoteProductDetailReq = new GetPromoteProductDetailReq();
        getPromoteProductDetailReq.setProductId(goodsIdBO.getProductId());
        getPromoteProductDetailReq.setShopAppid(goodsIdBO.getShopAppid());
        getPromoteProductDetailReq.setPlanType(planType);
        PromoteProductDetailDTO.Product product = null;
        try {
            PromoteProductDetailDTO productDetail = productService.getPromoteProductDetail(getPromoteProductDetailReq);
            product = productDetail.getProduct();
        } catch (BusinessException e) {
            if (API_ERROR_CODE_TO_DELETE_GOODS.contains(e.getCode())) {
                // 下架商品
                this.deleteGoods(redisKey, goodsIdBO);
                return false;
            }
        }
        if (Objects.nonNull(product)) {

            // 判断佣金状态
            PromoteProductDetailDTO.CommissionInfo commissionInfo = product.getCommissionInfo();
            if (Objects.equals(commissionInfo.getStatus(), 1)) {
                // 存储到Redis中
                stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJSONString(product), 1, TimeUnit.DAYS);
                return true;
            } else {
                // 定向计划才删除商品
                if (Objects.equals(planType,1)){
                    // 下架商品
                    this.deleteGoods(redisKey, goodsIdBO);
                }
                return false;
            }
        }
        return false;
    }

    /**
     * 获取机构合作商品
     *
     * @param goodsIdBO goodsIdBO
     * @return GetHeadSupplierProductDetailDTO.Product
     */
    public GetHeadSupplierProductDetailDTO.Product getHeadSupplierProductDetail(GoodsIdBO goodsIdBO) {
        String appKey = RequestUserHolder.getAppKey();
        String redisKey = RedisConstants.getHeadSupplierGoodsKey(appKey, goodsIdBO.getShopAppid(), goodsIdBO.getProductId());
        String json = stringRedisTemplate.opsForValue().get(redisKey);
        boolean match = true;
        if (StringUtils.isBlank(json)) {
            match = this.syncHeadSupplierProductDetail(goodsIdBO);
        }
        return match ? JsonUtils.parseObject(json, GetHeadSupplierProductDetailDTO.Product.class) : null;
    }

    /**
     * 同步机构合作商品
     *
     * @param goodsIdBO goodsIdBO
     * @return boolean
     */
    public boolean syncHeadSupplierProductDetail(GoodsIdBO goodsIdBO) {
        String appKey = RequestUserHolder.getAppKey();
        String redisKey = RedisConstants.getHeadSupplierGoodsKey(appKey, goodsIdBO.getShopAppid(), goodsIdBO.getProductId());
        GetHeadSupplierProductDetailReq getHeadSupplierProductDetailReq = new GetHeadSupplierProductDetailReq();
        getHeadSupplierProductDetailReq.setProductId(goodsIdBO.getProductId());
        getHeadSupplierProductDetailReq.setAppid(goodsIdBO.getShopAppid());
        GetHeadSupplierProductDetailDTO.Product product = null;
        try {
            GetHeadSupplierProductDetailDTO productDetail = productService.getHeadSupplierProductDetail(getHeadSupplierProductDetailReq);
            product = productDetail.getItem();
        } catch (BusinessException e) {
            if (Objects.equals("45009", e.getCode())) {
                // todo 接口限流 不处理
                return false;
            }
            if (API_ERROR_CODE_TO_DELETE_GOODS.contains(e.getCode())) {
                // 下架商品
                this.deleteGoods(redisKey, goodsIdBO);
                return false;
            }
        }
        if (Objects.nonNull(product)) {
            // 判断佣金状态
            PromoteProductDetailDTO.CommissionInfo commissionInfo = product.getCommissionInfo();
            if (Objects.equals(commissionInfo.getStatus(), 1)) {
                // 存储到Redis中
                stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJSONString(product), 1, TimeUnit.DAYS);
                return true;
            } else {
                // 下架商品
                this.deleteGoods(redisKey, goodsIdBO);
                return false;
            }
        }
        return false;
    }

    private void deleteGoods(String redisKey, GoodsIdBO goodsIdBO) {
        // 已下架推广 已清退
        // 直接删除下架
        goodsCategoryExtendService.deleteGoods(RequestUserHolder.getAppKey(), goodsIdBO);
        stringRedisTemplate.delete(redisKey);
        log.info("合作商品:{} 已过期,下架成功", JsonUtils.toJSONString(goodsIdBO));
    }

}
